{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Shared References and Mutability"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following sets up a shared reference between the variables my_var_1 and my_var_2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello\n",
      "hello\n"
     ]
    }
   ],
   "source": [
    "my_var_1 = 'hello'\n",
    "my_var_2 = my_var_1\n",
    "print(my_var_1)\n",
    "print(my_var_2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0x24c9144ca08\n",
      "0x24c9144ca08\n"
     ]
    }
   ],
   "source": [
    "print(hex(id(my_var_1)))\n",
    "print(hex(id(my_var_2)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "my_var_2 = my_var_2 + ' world!'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0x24c9144ca08\n",
      "0x24c9144fab0\n"
     ]
    }
   ],
   "source": [
    "print(hex(id(my_var_1)))\n",
    "print(hex(id(my_var_2)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Be careful if the variable type is mutable!\n",
    "\n",
    "Here we create a list (*my_list_1*) and create a variable (*my_list_2*) referencing the same list object:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3]\n",
      "[1, 2, 3]\n"
     ]
    }
   ],
   "source": [
    "my_list_1 = [1, 2, 3]\n",
    "my_list_2 = my_list_1\n",
    "print(my_list_1)\n",
    "print(my_list_2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As we can see they have the same memory address (shared reference):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0x24c9144fc48\n",
      "0x24c9144fc48\n"
     ]
    }
   ],
   "source": [
    "print(hex(id(my_list_1)))\n",
    "print(hex(id(my_list_2)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we modify the list referenced by *my_list_2*:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "my_list_2.append(4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*my_list_2* has been modified:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4]\n"
     ]
    }
   ],
   "source": [
    "print(my_list_2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And since my_list_1 references the same list object, it has also changed:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4]\n"
     ]
    }
   ],
   "source": [
    "print(my_list_1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As you can see, both variables still share the same reference:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0x24c9144fc48\n",
      "0x24c9144fc48\n"
     ]
    }
   ],
   "source": [
    "print(hex(id(my_list_1)))\n",
    "print(hex(id(my_list_2)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Behind the scenes with Python's memory manager\n",
    "----"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Recall from a few lectures back:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "a = 10\n",
    "b = 10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0x7559eaf0\n",
      "0x7559eaf0\n"
     ]
    }
   ],
   "source": [
    "print(hex(id(a)))\n",
    "print(hex(id(b)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Same memory address!!\n",
    "\n",
    "This is safe for Python to do because integer objects are **immutable**. \n",
    "\n",
    "So, even though *a* and *b* initially shared the same memory address, we can never modify *a*'s value by \"modifying\" *b*'s value. \n",
    "\n",
    "The only way to change *b*'s value is to change it's reference, which will never affect *a*."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "b = 15"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0x7559eaf0\n",
      "0x7559eb90\n"
     ]
    }
   ],
   "source": [
    "print(hex(id(a)))\n",
    "print(hex(id(b)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "However, for mutable objects, Python's memory manager does not do this, since that would **not** be safe."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "my_list_1 = [1, 2, 3]\n",
    "my_list_2 = [1, 2 , 3]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As you can see, although the two variables were assigned identical \"contents\", the memory addresses are not the same:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0x24c9146c5c8\n",
      "0x24c913c6848\n"
     ]
    }
   ],
   "source": [
    "print(hex(id(my_list_1)))\n",
    "print(hex(id(my_list_2)))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
